# -*- coding: utf-8 -*-
# Functions for encryption and signing based on PKCS#1 v1.5
# See http://www.di-mgt.com.au/rsa_alg.html#pkcs1schemes
r"""RSA module

This module can perform RSA public and private keys generating,
encryption, decryption, signing and verification.

NOTICE: This program is used for learning, there may have bugs
and potential security issues. Please DO NOT use this program
in production environment.

WARNING: Do not pass any Python traceback information to users
for it may leaks the type and the position of a failure when
it occurred.

Author: Kainan Zhu (Microdog)
E-mail: dlangu0393@gmail.com
East China Normal University - Software Engineering Institute

References:
    http://en.wikipedia.org/wiki/RSA_(algorithm)
    http://www.di-mgt.com.au/rsa_alg.html
    http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
    http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
    http://en.wikibooks.org/wiki/Algorithm_Implementation/Mathematics/Extended_Euclidean_algorithm
    ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
    https://bitbucket.org/sybren/python-rsa/
    http://code.activestate.com/recipes/572196-rsa/
    http://jhafranco.com/2012/01/29/rsa-implementation-in-python/

Example:
    Basic encryption, decryption and signing, verification:

    >>> import rsa
    >>> message = 'Hello, world!'
    >>> pub_key, pri_key = rsa.new_keys(1024)
    >>> cypher = rsa.encrypt(message, pub_key)
    >>> rsa.decrypt(cypher, pri_key)
    'Hello, world!'
    >>> signature = rsa.sign(message, pri_key, 'SHA-512')
    >>> rsa.verify(message, signature, pub_key)
    True

    Also working on binary data:

    >>> message = '\x02\x50\x00\x48\x80'
    >>> message
    '\x02P\x00H\x80'
    >>> cypher = rsa.encrypt(message, pub_key)
    >>> rsa.decrypt(cypher, pri_key)
    '\x02P\x00H\x80'
    >>> signature = rsa.sign(message, pri_key, 'SHA-512')
    >>> rsa.verify(message, signature, pub_key)
    True
    >>> rsa.verify(message.replace('\x00', ' '), signature, pub_key)
    Traceback (most recent call last):
      File "<console>", line 1, in <module>
      File "C:\Users\zkn\PycharmProjects\rsaLearning\rsa\pkcs1.py", line 241, in verify
        raise VerificationException('Verification failed!')
    VerificationException: Verification failed!

    Warning: Here we can see that Python traceback leaks the information about the
    position where the exception raised, these information may be used to deduce.
    So please catch these exceptions and DO NOT send any information to your users.

Speed test:
    Key generating running on i7-2640M @ 2.8GHz:

    >>> print('Python %s on %s' % (sys.version, sys.platform))
    Python 2.7.4 (default, Apr  6 2013, 19:55:15) [MSC v.1500 64 bit (AMD64)] on win32
    >>> time1 = time.time(); rsa.new_keys(512); time2 = time.time()
    (<rsa.key.PublicKey object at 0x0000000002963A90>, <rsa.key.PrivateKey object at 0x0000000002963DA0>)
    >>> time2 - time1
    0.15700006484985352
    >>> time1 = time.time(); rsa.new_keys(1024); time2 = time.time()
    (<rsa.key.PublicKey object at 0x0000000002963DA0>, <rsa.key.PrivateKey object at 0x0000000002963BA8>)
    >>> time2 - time1
    0.33899998664855957
    >>> time1 = time.time(); rsa.new_keys(2048); time2 = time.time()
    (<rsa.key.PublicKey object at 0x0000000002963B00>, <rsa.key.PrivateKey object at 0x0000000002963A90>)
    >>> time2 - time1
    12.696000099182129
"""

__author__ = 'Kainan Zhu'
__email__ = 'dlangu0393@gmail.com'
__copyright__ = 'Copyright 2013, Kainan Zhu'
__version__ = '0.1.1'
__date__ = '2013-06-09'

from rsa.key import new_keys, generate_prime, generate_p_q, generate_keys, PublicKey, PrivateKey
from rsa.pkcs1 import encrypt, decrypt, sign, verify
from rsa.common import DecryptionException, VerificationException, CryptoException

__all__ = ['new_keys', 'generate_p_q', 'generate_keys', 'generate_prime',
           'encrypt', 'decrypt', 'sign', 'verify',
           'DecryptionException', 'VerificationException',
           'CryptoException', 'PublicKey', 'PrivateKey']
